Skip to main content

Authentication

Learn how SvelteBolt's authentication system works and how to add new OAuth providers for seamless user login.

Overview​

SvelteBolt uses Supabase Auth for authentication, providing multiple sign-in methods:

  • Magic Link - Passwordless login via email
  • Password Authentication - Traditional email/password login
  • OAuth Providers - Social login with Google, GitHub, Twitter, and more

How Authentication Works​

Current Implementation​

The authentication system is built around these key components:

  1. Login/Signup Forms - Located in src/lib/components/
  2. Auth Actions - Server-side handlers in src/routes/auth/+page.server.ts
  3. Database Adapter - Abstraction layer in src/lib/server/database/
  4. Auth Callbacks - Handle OAuth redirects in src/routes/api/auth/

Adding New OAuth Providers​

Step 1: Configure in Supabase​

  1. Go to your Supabase Dashboard

    • Navigate to Authentication → Providers
  2. Enable your desired provider (e.g., Discord, LinkedIn, etc.)

    • Click on the provider you want to add
    • Toggle Enable to true
  3. Add provider credentials

    • Client ID: From your OAuth app
    • Client Secret: From your OAuth app
    • Redirect URL: Copy the provided URL for your provider setup
  4. Configure redirect URL in your OAuth app

    • Use the format: https://your-project-id.supabase.co/auth/v1/callback

Step 2: Add Provider to Your Forms​

Add the new provider button to both login and signup forms:

Login Form (src/lib/components/login-form.svelte)​

<!-- Add this after the existing OAuth providers -->
<form action="/auth?/oauth" method="POST">
<input type="hidden" name="provider" value="discord" />
<button type="submit" variant="outline" class="w-full">
<Icon icon="logos:discord-icon" />
Login with Discord
</button>
</form>

Signup Form (src/lib/components/signup-form.svelte)​

<!-- Add this after the existing OAuth providers -->
<form action="/auth?/oauth" method="POST">
<input type="hidden" name="provider" value="discord" />
<button type="submit" variant="outline" class="w-full">
<Icon icon="logos:discord-icon" />
Sign up with Discord
</button>
</form>

Step 3: Verify Server Implementation​

The OAuth action in src/routes/auth/+page.server.ts already handles any provider:

oauth: async ({ request, url, locals }) => {
const db = createDatabaseAdapter(locals);
const formData = await request.formData();
const provider = (formData.get("provider") as Provider) ?? "";

const { data, error } = await db.auth.signInWithOAuth(provider, {
redirectTo: `${url.origin}/api/auth/callback`,
});

if (error) {
console.error(error);
redirect(303, "/auth/login");
}

redirect(303, data.url);
};

This automatically works with any Supabase-supported provider!

Supported OAuth Providers​

Supabase supports these OAuth providers out of the box:

  • Social: Google, GitHub, Twitter, Facebook, Discord
  • Professional: LinkedIn, Microsoft, Slack, Notion
  • Developer: GitLab, Bitbucket, WorkOS
  • Other: Apple, Spotify, Twitch, Zoom, Keycloak

Common OAuth Provider Setups​

Discord​

  1. Create Discord Application

  2. Configure OAuth2

    • Add redirect URI: https://your-project-id.supabase.co/auth/v1/callback
    • Copy Client ID and Client Secret
  3. Add to Supabase

    • Enable Discord provider
    • Paste credentials

LinkedIn​

  1. Create LinkedIn App

  2. Configure OAuth

    • Add redirect URL in app settings
    • Copy Client ID and Client Secret
  3. Add to Supabase

    • Enable LinkedIn OIDC provider
    • Paste credentials

Microsoft/Azure​

  1. Create Azure App Registration

    • Go to Azure Portal
    • Register new application
    • Configure authentication
  2. Set Redirect URI

    • Add the Supabase callback URL
    • Copy Application (client) ID and secret
  3. Add to Supabase

    • Enable Azure provider
    • Paste credentials

Code Locations for Customization​

Form Components​

src/lib/components/
├── login-form.svelte # Login page OAuth buttons
└── signup-form.svelte # Signup page OAuth buttons

Server Actions​

src/routes/auth/
├── +page.server.ts # OAuth action handler
└── schema.ts # Form validation schema

Auth Callbacks​

src/routes/api/auth/
├── callback/+server.ts # OAuth callback handler
├── confirm/+server.ts # Email confirmation handler
└── logout/+server.ts # Logout handler

Database Adapter​

src/lib/server/database/
├── index.ts # Database adapter factory
├── supabase.ts # Supabase implementation
└── types.ts # Interface definitions

Adding Custom Icons​

SvelteBolt uses @iconify/svelte for icons. Find provider icons at Iconify:

<!-- Examples -->
<Icon icon="logos:discord-icon" />
<Icon icon="logos:linkedin-icon" />
<Icon icon="logos:microsoft-icon" />
<Icon icon="simple-icons:slack" />

Customization Tips​

Styling OAuth Buttons​

All OAuth buttons use the same base styling. Customize them in your form components:

<button type="submit" variant="outline" class="w-full custom-oauth-button">
<Icon icon="your-icon" />
Sign in with Provider
</button>

Error Handling​

OAuth errors are automatically handled by the server action. Custom error messages can be added:

if (error) {
console.error(`OAuth error for ${provider}:`, error);
// Add custom error handling here
redirect(303, "/auth/login?error=oauth_failed");
}

Provider-Specific Scopes​

Some providers need specific scopes. Configure them in Supabase:

// This is handled in Supabase dashboard, not in code
// But you can pass additional options:
const { data, error } = await db.auth.signInWithOAuth(provider, {
redirectTo: `${url.origin}/api/auth/callback`,
options: {
scopes: "email profile", // Provider-specific scopes
},
});

Troubleshooting​

Common Issues​

"Invalid redirect URI"

  • Ensure redirect URI matches exactly in provider settings
  • Check for trailing slashes or protocol mismatches

"Provider not enabled"

  • Verify provider is enabled in Supabase dashboard
  • Check credentials are correctly entered

"CORS errors"

  • Ensure site URL is configured in Supabase
  • Check redirect URLs are whitelisted

Next Steps​